<?php

/**
 * Created by PhpStorm.
 * User: Sing
 * Date: 16/10/25
 * Time: 20:33
 */
class sing_queue
{
    function __construct()
    {

    }
    //入队
    function zadd($Queue , $value){
        $minTime = microtime(true);
        $values = array($minTime, $value);
        $add = redis2('zadd',$Queue , $values);
        if($add){
            return $this->position($Queue , $minTime);
        }else{
            return false;
        }
    }
    //出队
    function zrem($Queue, $value){
        redis2('zrem',$Queue, $value);
    }
    //队列中的位置
    function position($Queue, $minTime){
        //当前等待位置
        $limit = array(0, $minTime);
        return redis2('zcount',$Queue,$limit);
    }
    //取出固定数量
    function keygetnum($Queue , $len = 0){
        $len = $len-1;
        $values =  array(0,$len);
        return redis2('zrange',$Queue , $values);
    }
    //排队,入队
    /*
     * 返回值,当前在队列中的位置,0为已经入队
     * $Name 队列标识
     * $score 排序,应传入微秒
     * $value 值
     * $length 队列长度
     * $time 超时时间
     *
     * 返回值 0为已加入到服务队列,可以继续进行操作
     * 大于 0  为当前需要等待数量
     * */
    public function queue($Name , $value , $length = 300 , $time =600){

        $nowMark = 0;
        //Luck$Name 入队
        //Wait$Name 队列等待中
        $LuckQueue = 'Luck'.$Name;
        $WaitQueue = 'Wait'.$Name;

        //ZREMRANGEBYSCORE 移除超时
        //默认600秒
        $DelTime = TIME-$time;
        $values = array(0,$DelTime);
        redis2('zremrangebyscore',$LuckQueue, $values);

        $GetScore = redis2('zscore',$LuckQueue , $value);
        if($GetScore){     //已在服务队列
            //需要更新队里中的 score,防止被清除
            $this->zadd($LuckQueue, $value);
            $nowMark = 0;
        }else{      //排队处理
            $WaitScore = redis2('zscore',$WaitQueue , $value);  //在等待队列查找当前key
            if(!$WaitScore) {
                //加入等待队列
                $this->zadd($WaitQueue, $value);      //加入后等待队列的长度
            }
        }
        
        //取当前服务队列数量
        $Lucknum = redis2('zcard',$LuckQueue);
        //进行补位操作
        $num = $length-$Lucknum;        //补位数量
        if($num > 0){ //需要补位
            $isRun = redis2('get','Run'.$Name);
            if(TIME-$isRun > 25){    //补位操作大于25秒就重新补位
                redis2('set','Run'.$Name,TIME);
                $list = $this->keygetnum($WaitQueue , $num);
                foreach($list as $v){
                    $this->zadd($LuckQueue , $v);
                    //在等待队列出队
                    $this->zrem($WaitQueue, $v);
                }
                redis2('set','Run'.$Name,0);
            }
        }
        $WaitScore = redis2('zscore',$WaitQueue , $value);  //在等待队列查找当前key
        if($WaitScore){
            $nowMark = $this->position($WaitQueue, $WaitScore); //队列后的位置
        }else{
            //$GetScore = redis2('zscore',$LuckQueue , $value);
            //if($GetScore)  $nowMark = 0;
            //else $nowMark = -1;
            $nowMark = 0;
        }
        //$nowMark = $wailen-$num>0?$wailen-$num:0;     //补位后的位置
        return $nowMark;

    }
    //出队
    public function remove($Name , $key){
        $LuckQueue = 'Luck'.$Name;
        $this->zrem($LuckQueue , $key);
    }
    //清除等待队列
    public function rmWait($Name){
        $WaitQueue = 'Wait'.$Name;
        $DelTime = microtime(true);
        $values = array(0,$DelTime);
        redis2('zremrangebyscore',$WaitQueue, $values);
    }
}